﻿using SD.Infrastructure.DTOBase;
using SD.OpcServer.IAppService.DTOs;
using SD.OpcServer.IAppService.Interfaces;
using SD.OpcServer.Models.Base;
using SD.OpcServer.Models.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.ServiceModel;

namespace SD.OpcServer.Host.Services
{
    /// <summary>
    /// OPC服务契约实现
    /// </summary>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class OpcServerContract : IOpcServerContract
    {
        //命令部分

        #region # 创建变量 —— void CreateVariable(string variableNo, string variableName...
        /// <summary>
        /// 创建变量
        /// </summary>
        /// <param name="variableNo">变量编号</param>
        /// <param name="variableName">变量名称</param>
        /// <param name="dataType">数据类型</param>
        /// <param name="unit">单位</param>
        /// <param name="keepRecord">是否记录历史</param>
        /// <param name="equipmentNo">设备编号</param>
        /// <param name="description">描述</param>
        /// <param name="valueDescriptions">值描述字典</param>
        public void CreateVariable(string variableNo, string variableName, string dataType, string unit, bool keepRecord, string equipmentNo, string description, IDictionary<string, string> valueDescriptions)
        {
            using (DbSession dbSession = new DbSession())
            {
                Variable variable = new Variable(variableNo, variableName, dataType, unit, keepRecord, equipmentNo, description, valueDescriptions);
                dbSession.Set<Variable>().Add(variable);

                dbSession.SaveChanges();
            }
        }
        #endregion

        #region # 修改变量 —— void UpdateVariable(Guid variableId, string variableName...
        /// <summary>
        /// 修改变量
        /// </summary>
        /// <param name="variableId">变量Id</param>
        /// <param name="variableName">变量名称</param>
        /// <param name="unit">单位</param>
        /// <param name="keepRecord">是否记录历史</param>
        /// <param name="equipmentNo">设备编号</param>
        /// <param name="description">描述</param>
        /// <param name="valueDescriptions">值描述字典</param>
        public void UpdateVariable(Guid variableId, string variableName, string unit, bool keepRecord, string equipmentNo, string description, IDictionary<string, string> valueDescriptions)
        {
            using (DbSession dbSession = new DbSession())
            {
                Variable variable = dbSession.Set<Variable>().Single(x => x.Id == variableId);
                variable.UpdateInfo(variableName, unit, keepRecord, equipmentNo, description, valueDescriptions);

                dbSession.SaveChanges();
            }
        }
        #endregion

        #region # 删除变量 —— void RemoveVariable(Guid variableId)
        /// <summary>
        /// 删除变量
        /// </summary>
        /// <param name="variableId">变量Id</param>
        public void RemoveVariable(Guid variableId)
        {
            using (DbSession dbSession = new DbSession())
            {
                Variable variable = dbSession.Set<Variable>().Single(x => x.Id == variableId);

                dbSession.Set<Variable>().Remove(variable);
                dbSession.SaveChanges();
            }
        }
        #endregion


        //查询部分

        #region # 分页获取变量列表 —— PageModel<VariableInfo> GetVariablesByPage(int pageIndex...
        /// <summary>
        /// 分页获取变量列表
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>变量列表</returns>
        public PageModel<VariableInfo> GetVariablesByPage(int pageIndex, int pageSize)
        {
            using (DbSession dbSession = new DbSession())
            {
                IOrderedQueryable<Variable> variables = dbSession.Set<Variable>().OrderBy(x => x.Number);

                int rowCount = variables.Count();
                int pageCount = (int)Math.Ceiling(rowCount * 1.0 / pageSize);
                IList<Variable> pagedResult = variables.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();

                IEnumerable<VariableInfo> variableInfos =
                    from variable in pagedResult
                    select new VariableInfo
                    {
                        Id = variable.Id,
                        Number = variable.Number,
                        Name = variable.Name,
                        DataType = variable.DataType,
                        Unit = variable.Unit,
                        KeepRecord = variable.KeepRecord,
                        NodeId = variable.NodeId,
                        EquipmentNo = variable.EquipmentNo,
                        Description = variable.Description,
                        ValueDescriptions = variable.ValueDescriptions
                    };

                return new PageModel<VariableInfo>(variableInfos, pageIndex, pageSize, pageCount, rowCount);
            }
        }
        #endregion

        #region # 根据编号获取变量字典 —— {string, VariableInfo} GetVariablesByNo(IEnumerable<string> variableNos)
        /// <summary>
        /// 根据编号获取变量字典
        /// </summary>
        /// <param name="variableNos">变量编号集</param>
        /// <returns>变量字典</returns>
        public IDictionary<string, VariableInfo> GetVariablesByNo(IEnumerable<string> variableNos)
        {
            #region # 验证

            string[] variableNos_ = variableNos?.Distinct().ToArray() ?? new string[0];
            if (!variableNos_.Any())
            {
                return new Dictionary<string, VariableInfo>();
            }

            #endregion

            using (DbSession dbSession = new DbSession())
            {
                var entities = from entity in dbSession.Set<Variable>()
                               where variableNos_.Contains(entity.Number)
                               select new { entity.Number, entity };
                IDictionary<string, Variable> dictionary = entities.ToDictionary(x => x.Number, x => x.entity);

                IDictionary<string, VariableInfo> dictionaryInfo = new Dictionary<string, VariableInfo>();
                foreach (KeyValuePair<string, Variable> kv in dictionary)
                {
                    Variable variable = kv.Value;
                    VariableInfo variableInfo = new VariableInfo
                    {
                        Id = variable.Id,
                        Number = variable.Number,
                        Name = variable.Name,
                        DataType = variable.DataType,
                        Unit = variable.Unit,
                        KeepRecord = variable.KeepRecord,
                        NodeId = variable.NodeId,
                        EquipmentNo = variable.EquipmentNo,
                        Description = variable.Description,
                        ValueDescriptions = variable.ValueDescriptions
                    };
                    dictionaryInfo.Add(kv.Key, variableInfo);
                }

                return dictionaryInfo;
            }
        }
        #endregion

        #region # 分页获取变量历史列表 —— PageModel<VariableHistoryInfo> GetVariableHistorysByPage(string variableNo...
        /// <summary>
        /// 分页获取变量历史列表
        /// </summary>
        /// <param name="variableNo">变量编号</param>
        /// <param name="startTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>变量历史列表</returns>
        public PageModel<VariableHistoryInfo> GetVariableHistorysByPage(string variableNo, DateTime? startTime, DateTime? endTime, int pageIndex, int pageSize)
        {
            using (DbSession dbSession = new DbSession())
            {
                Expression<Func<VariableHistory, bool>> condition =
                    x =>
                        (string.IsNullOrEmpty(variableNo) || x.VariableNo == variableNo) &&
                        (startTime == null || x.AddedTime >= startTime) &&
                        (endTime == null || x.AddedTime <= endTime);

                IOrderedQueryable<VariableHistory> variableHistories = dbSession.Set<VariableHistory>().Where(condition).OrderByDescending(x => x.AddedTime);

                int rowCount = variableHistories.Count();
                int pageCount = (int)Math.Ceiling(rowCount * 1.0 / pageSize);
                IList<VariableHistory> pagedResult = variableHistories.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();

                IEnumerable<VariableHistoryInfo> variableHistoryInfos =
                    from variableHistory in pagedResult
                    select new VariableHistoryInfo
                    {
                        Id = variableHistory.Id,
                        VariableNo = variableHistory.VariableNo,
                        VariableName = variableHistory.VariableName,
                        DataType = variableHistory.DataType,
                        PreviousValue = variableHistory.PreviousValue,
                        PreviousValueDescription = variableHistory.PreviousValueDescription,
                        CurrentValue = variableHistory.CurrentValue,
                        CurrentValueDescription = variableHistory.CurrentValueDescription,
                        Unit = variableHistory.Unit,
                        AddedTime = variableHistory.AddedTime
                    };

                return new PageModel<VariableHistoryInfo>(variableHistoryInfos, pageIndex, pageSize, pageCount, rowCount);
            }
        }
        #endregion
    }
}
